package pers.cz.redis;

import cn.hutool.core.date.DateUtil;
import pers.cz.commons.collection_server.InterfaceSyncToDb;
import pers.cz.model.AutoCollectTestCaseSql;
import pers.cz.thread.ThreadUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;

import java.util.ArrayList;
import java.util.List;

/**
 * 接口触发sql同步
 * @program: PostGirl-panent
 * @description: InterfaceSqlSyncThread
 * @author: Cheng Zhi
 * @create: 2022-02-18 18:07
 **/
public class InterfaceSqlSyncThread implements Runnable{

    private Logger logger = LoggerFactory.getLogger(InterfaceSqlSyncThread.class);

    private Jedis resource;

    private volatile Boolean flag = false;

    private final Integer timeOut = 0;          // 设置为0表示阻塞

    private final Long SLEEP_TIME = 60000L;     // 提交数据库间隔时间

    private final Integer BATCH_NUMBER = 200;   // 批量提交数

    private Thread t;
    // 初始化一个指定长度的list防止扩容带来的性能损耗
    private final List<AutoCollectTestCaseSql> list = new ArrayList<AutoCollectTestCaseSql>(1000);

    public InterfaceSqlSyncThread(Jedis resource) {
        this.resource = resource;

        // 初始化一个线程用来提交数据库
        t = new Thread() {
            @Override
            public void run() {
                ThreadUtils.doSleep(240000);
                doTask();
            }

            private void doTask() {
                while(true) {
                    List<AutoCollectTestCaseSql> todo = null;
                    synchronized (list) {
                        if(list.size()>0){
                            todo = new ArrayList<AutoCollectTestCaseSql>(list);
                            list.clear();
                        }
                    }
                    if(todo != null){
                        // 批量插入数据库
                        InterfaceSyncToDb.SyncSqlToDb(todo);
                    }
                    ThreadUtils.doSleep(SLEEP_TIME);
                }
            }
        };
        t.start();
    }


    @Override
    public void run() {
        // 同步的时候要先删除busiCode一样的，然后再插入最新的，保证数据库中的为最新的数据，这里需要小心锁的问题。
        while(!flag) {
            delSync();
        }
    }

    /**
     * 同步进程
     */
    public void delSync() {

        // 消费
        List<String> interfaceListQueue = resource.brpop(timeOut,"SQLCOLLECTIONQUEUE");
        logger.debug(Thread.currentThread().getName() + "------接收到同步SQL请求-------");
        if (interfaceListQueue != null && interfaceListQueue.size() > 0) {

            String interfaces = interfaceListQueue.get(1); // 取下标为1的， 下标为0表示的是key
            String[] interfacesArrays = interfaces.split("\\|\\|");
            if (interfacesArrays.length > 0) {

                String source = "";
                String busiCode = "";
                String threadSts = "";
                String runTime = "";
                String runSql = "";
                if (interfacesArrays.length > 4) {
                    source = interfacesArrays[0];
                    busiCode = interfacesArrays[1];
                    threadSts = interfacesArrays[2]; // 线程标识
                    runTime = interfacesArrays[3];
                    runSql = interfacesArrays[4];
                } else {
                    source = interfacesArrays[0];
                    busiCode = interfacesArrays[1];
                    runTime = interfacesArrays[2];
                    runSql = interfacesArrays[3];
                }

                if (busiCode == null || busiCode.equals("null")) {
                    // 其他线程的不处理,只处理接口相关的
                    return;
                }
                AutoCollectTestCaseSql autoCollectTestCaseSql = new AutoCollectTestCaseSql();
                autoCollectTestCaseSql.setBusiCode(busiCode);
                autoCollectTestCaseSql.setRunTime(runTime);
                autoCollectTestCaseSql.setRunSql(runSql);
                autoCollectTestCaseSql.setExt1(source);
                autoCollectTestCaseSql.setExt2(threadSts);
                autoCollectTestCaseSql.setSyncTime(DateUtil.date());
                doInsert(autoCollectTestCaseSql);
            }
        }
    }

    private void doInsert(AutoCollectTestCaseSql autoCollectTestCaseSql) {
        List<AutoCollectTestCaseSql> todo = null;
        synchronized (list) {
            list.add(autoCollectTestCaseSql);
            if(list.size()>=BATCH_NUMBER){
                todo=new ArrayList<AutoCollectTestCaseSql>(list);
                list.clear();
            }
        }
        if(todo!=null){
            // 批量插入数据库
            InterfaceSyncToDb.SyncSqlToDb(todo);
        }
    }
}
